package com.dragonwu.service.impl;

import com.dragonwu.constant.Constants;
import com.dragonwu.model.LoginUser;
import com.dragonwu.model.OnlineUser;
import com.dragonwu.model.param.LoginParam;
import com.dragonwu.model.vo.LoginVo;
import com.dragonwu.service.EasyCaptchaService;
import com.dragonwu.service.LoginService;
import com.dragonwu.utils.JwtUtil;
import com.dragonwu.utils.RedisUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * @author DragonWu
 * @since 2022-10-07 19:02
 **/
@Service
public class LoginServiceImpl implements LoginService {

    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private EasyCaptchaService easyCaptchaService;


    @Override
    public LoginVo login(LoginParam loginParam) throws RuntimeException {
        //判断验证码是否正确
        easyCaptchaService.verifyCaptchaCode(loginParam.getUuid(), loginParam.getCaptcha());

        //AuthenticationManager authenticate进行用户认证
        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginParam.getUsername(), loginParam.getPassword());
        Authentication authenticate = authenticationManager.authenticate(authenticationToken);
        //如果认证没通过给出相应的提示
        if (Objects.isNull(authenticate)) {
            throw new RuntimeException(Constants.LOGIN_ERROR);
        }

        //如果认证通过了，获取UserDetailService返回过期的UserDetail对象
        LoginUser loginUser = (LoginUser) authenticate.getPrincipal();
        //使用primaryKey生成JWT
        String primaryKey = loginUser.getSysUser().getUserId().toString();
        Map<String, Object> claims = new HashMap<>();
        claims.put(JwtUtil.JWT_PRIMARY_KEY, primaryKey);
        String token = JwtUtil.createJwt(claims, JwtUtil.DEFAULT_EXPIRE_MINUTES);

        //把用户信息存入redis
        OnlineUser onlineUser = new OnlineUser(loginUser.getSysUser(), loginUser.getJurisdictionToString());
        redisUtil.setObject(Constants.ONLINE_PRE + primaryKey, onlineUser, JwtUtil.DEFAULT_EXPIRE_MINUTES, TimeUnit.MINUTES);

        //将返回结果封装达到返回对象
        return new LoginVo(loginUser.getSysUser(), loginUser.getJurisdiction(), token);
    }

    @Override
    public void logout() throws RuntimeException {
        try {
            //获取SecurityContextHolder里的用户id
            UsernamePasswordAuthenticationToken authentication =
                    (UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
            OnlineUser onlineUser = (OnlineUser) authentication.getPrincipal();
            String primaryKey = String.valueOf(onlineUser.getSysUser().getUserId());
            //删除redis中的值
            redisUtil.deleteObject(Constants.ONLINE_PRE + primaryKey);
        } catch (Exception e) {
            throw new RuntimeException(Constants.LOGOUT_FAIL);
        }
    }

    @Override
    public Map<String, String> getCaptcha() throws IOException {
        return easyCaptchaService.outputCaptchaImg(EasyCaptchaService.CAPTCHA_TYPE_GIF);
    }
}
